package com.wolfman.socket.server.server;

import com.alibaba.fastjson.JSON;
import com.wolfman.socket.server.handler.Handler;
import com.wolfman.socket.server.pojo.ResponseHeader;
import com.wolfman.socket.server.pojo.ServerConfig;
import com.wolfman.socket.server.pojo.SocketResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Title
 * @Description
 * @Author WolfMan
 * @Date 2022/11/25 9:56
 * @Email 2370032534@qq.com
 */
public class Server extends ServerAbstract {

    /**
     * 端口
     */
    private static final int PORT = 8000;
    /**
     * 核心线程数
     */
    private static final int CORE_POOL_SIZE = 32;
    /**
     * 最大线程数量
     */
    private static final int MAX_POOL_SIZE = 64;
    /**
     * 队列列表
     */
    private static final int QUEUE_CAPACITY = 10000;
    /**
     * 保活时间
     */
    private static final Long KEEP_ALIVE_TIME = 1L;
    /**
     * 处理器
     */
    private static Handler handler = new Handler();
    /**
     * 日志服务
     */
    private Logger logger = LoggerFactory.getLogger(Server.class);


    public Server() {
        super.init();
    }

    @Override
    protected void onServerStart(ServerSocket serverSocket) {
        logger.info("服务端启动，监听端口：" + serverSocket.getLocalPort());
    }

    @Override
    protected ServerConfig initServerConfig() {
        ServerConfig serverConfig = new ServerConfig();
        //设置监听端口
        serverConfig.setPort(PORT);
        return serverConfig;
    }

    @Override
    protected ThreadPoolExecutor initServerExecutor() {
        return new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());
    }

    @Override
    protected void onServerClose(ServerSocket serverSocket) {
        try {
            serverSocket.close();
        } catch (IOException e) {
            logger.error("服务器关闭异常", e);
        }
    }

    @Override
    protected void onClientClose(Socket socket, BufferedReader reader, BufferedWriter writer) {
        try {
            socket.close();
            reader.close();
            writer.close();
            logger.info("客户端[" + socket.getInetAddress() + ":" + socket.getPort() + "]已关闭");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onClientConnect(Socket socket) {
        logger.info("客户端[" + socket.getInetAddress() + ":" + socket.getPort() + "]已连接");
    }

    @Override
    protected void onServerException(IOException e) {
        logger.error("服务器运行异常", e);
    }

    @Override
    protected void onClientMessage(Socket socket, String msg, BufferedWriter writer) {
        logger.info("客户端发送数据：" + msg);
        //获取控制器处理消息
        Object result = handler.handle(msg);
        try {
            // 回复客户发送的消息
            writer.write(JSON.toJSON(new SocketResponse(new ResponseHeader(LocalDateTime.now()), result)) + "\n");
            //防止消息遗留到本地缓冲区，保证马上发送出去
            writer.flush();
        } catch (IOException e) {
            logger.error("服务器回复消息异常:", e);
        }
    }

    public void run() {
        super.bootstrap();
    }
}
